package com.dora.mega.data.transfer.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dora.mega.data.transfer.domain.ActResultLog;
import com.dora.mega.data.transfer.domain.ActResultLogVO;
import com.dora.mega.data.transfer.fecade.listener.ExcelListener;
import com.dora.mega.data.transfer.fecade.listener.SyncExcelListener;
import com.dora.mega.data.transfer.fecade.util.ExcelUtil;
import com.dora.mega.data.transfer.mapper.ActResultLogMapper;
import com.dora.mega.data.transfer.service.IActResultLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import static com.dora.mega.data.transfer.fecade.util.ExcelUtil.setExportHeader;

/**
 * 日志服务impl
 *
 * @author Clarence
 * @date 2024/04/04
 */
@Slf4j
@Service
public class ActResultLogServiceImpl extends ServiceImpl<ActResultLogMapper, ActResultLog> implements IActResultLogService {

    @Override
    public void exportExcel(HttpServletResponse response) throws IOException {
        List<ActResultLog> data = this.list();
        ExcelUtil.exportExcel(response, "测试导出", ActResultLogVO.class, data);
    }

    @Override
    public void exportExcel1(HttpServletResponse response) throws IOException, InterruptedException {
        setExportHeader(response,"测试导出");
        //分页导出实现,暂定每页为5k条数据,可以根据内存变化调整,
        long total = this.count();
        long pageSize = 5000;
        long pages = total / pageSize;
        try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream(), ActResultLog.class).build()) {
            // 创建一个写入工作表
            WriteSheet writeSheet = EasyExcel.writerSheet(0, "Sheet1").build();
            for (long i = 0; i < pages; i++) {
                Page<ActResultLog> page = this.page(new Page<>(i, pageSize));
                List<ActResultLog> data = page.getRecords();
                excelWriter.write(data, writeSheet);
                log.info("第：{}页数据，写入完成", i + 1);
            }
        }
    }

    @Override
    public void exportExcel2(HttpServletResponse response) throws IOException, InterruptedException {
        setExportHeader(response,"测试单个sheet导出");
        long count = this.count();
        //这里的页数，可以灵活调整，建议小一些，避免连接池过大的问题
        int pages = 10;
        Long size = count / pages;
        ExecutorService executorService = Executors.newFixedThreadPool(pages);
        CountDownLatch countDownLatch = new CountDownLatch(pages);
        Map<Integer, Page<ActResultLog>> pageMap = new HashMap<>();
        for (int i = 0; i < pages; i++) {
            int finalI = i;
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    Page<ActResultLog> page = new Page<>();
                    page.setCurrent(finalI + 1);
                    page.setSize(size);
                    Page<ActResultLog> selectPage = baseMapper.selectPage(page, null);
                    log.info("查询到第{}页数据：{}",finalI + 1, selectPage.getRecords().size());
                    pageMap.put(finalI, selectPage);
                    countDownLatch.countDown();
                }
            });
        }
        countDownLatch.await();
        WriteSheet writeSheet = EasyExcel.writerSheet(0, "Sheet1").build();
        try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream(), ActResultLog.class).build()) {
            for (Map.Entry<Integer, Page<ActResultLog>> entry : pageMap.entrySet()) {
                Page<ActResultLog> salariesPage = entry.getValue();
                excelWriter.write(salariesPage.getRecords(), writeSheet);
            }
        }
    }

    @Override
    public void exportExcel3(HttpServletResponse response) throws IOException, InterruptedException {
        setExportHeader(response,"测试多个sheet导出");
        long count = this.count();
        //这里的页数，可以灵活调整，建议小一些，避免连接池过大的问题
        int pages = 10;
        Long size = count / pages;
        ExecutorService executorService = Executors.newFixedThreadPool(pages);
        CountDownLatch countDownLatch = new CountDownLatch(pages);
        Map<Integer, Page<ActResultLog>> pageMap = new HashMap<>();
        for (int i = 0; i < pages; i++) {
            int finalI = i;
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    Page<ActResultLog> page = new Page<>();
                    page.setCurrent(finalI + 1);
                    page.setSize(size);
                    Page<ActResultLog> selectPage = baseMapper.selectPage(page, null);
                    log.info("查询到第{}页数据：{}",finalI + 1, selectPage.getRecords().size());
                    pageMap.put(finalI, selectPage);
                    countDownLatch.countDown();
                }
            });
        }
        countDownLatch.await();
        try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream(), ActResultLog.class).build()) {
            for (Map.Entry<Integer, Page<ActResultLog>> entry : pageMap.entrySet()) {
                Integer num = entry.getKey();
                Page<ActResultLog> salariesPage = entry.getValue();
                WriteSheet writeSheet = EasyExcel.writerSheet(num, "sheet" + num).build();
                excelWriter.write(salariesPage.getRecords(), writeSheet);
            }
        }
    }

    @Override
    public void importExcel(MultipartFile file) throws IOException {
        EasyExcel.read(file.getInputStream(), ActResultLog.class, new ExcelListener(this)).sheet().doRead();
    }

    @Resource
    private SyncExcelListener syncExcelListener;

    private ExecutorService executorService = Executors.newFixedThreadPool(20);

    @Override
    public void importExcel1(MultipartFile file) throws IOException {
        // 开20个线程分别处理20个sheet
        List<Callable<Object>> tasks = new ArrayList<>();
        for (int i = 0; i < 20; i++) {
            int num = i;
            tasks.add(() -> {
                EasyExcel.read(file.getInputStream(), ActResultLog.class, syncExcelListener)
                        .sheet(num).doRead();
                return null;
            });
        }
        try {
            executorService.invokeAll(tasks);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}
